import ajax from '@/uni_modules/u-ajax/js_sdk';
import {
  checkStatus
} from '../checkStatus';
import {
  joinTimestamp,
  formatRequestDate
} from '../helper';
import config from "@/config/index.config";
import {
  getApiUrl,
  getFileUrl,
  getUploadUrl
} from "@/utils/baseUrl";
import {
  merge
} from "@/utils/merge";
import {
  isString,
  isNumber,
  isBoolean
} from "@/utils/is";
import store from '@/store';
import {
  getCurrentRequestlang,
  useI18n
} from '@/locales/setupI18n';
import {
  requestMethodEnum,
  contentTypeEnum
} from '@/enums/httpEnum';

/** 配置说明，不可用 */
const demoConfig = {
  // 请求根地址（String）。自动加在 url 前面，除非 url 是一个绝对地址 (http 或 https 开头)。
  baseURL: '',
  // 开发者服务器接口地址（String）。
  url: '',
  // 请求的参数（Object）。如果在创建实例时设定该属性，后面的实例请求方法会合并 data。
  data: null,
  // 请求头（Object）。header 中不能设置 Referer。这里的 header 也可以为不同请求方式添加对应的请求头（注意这里的请求方式属性要小写），以及 common 公共请求头属性。
  // header 不仅可以在创建实例配置中，也可以在请求拦截器中修改配置。
  header: null,
  // 请求方式（String）。在实例中配置可定义 ajax() 方法在没有传入指定的 method 的情况下的请求方式。
  method: 'GET',
  // URL 的 query 参数（Object）。会将数据转换为 query string 拼接在 URL 上。
  query: null,
  // URL 的 params 参数（Object）。会替换掉 URL 上的 params 字段。
  params: null,
  // 超时时间（Number）。单位 ms。
  timeout: 30000,
  // 返回数据类型（String）。如果设为 json，会尝试对返回的数据做一次 JSON.parse。
  dataType: 'json',
  // 响应的数据类型（'text' ｜ 'arraybuffer'）。
  responseType: 'text',
  // 是否验证 ssl 证书（Boolean）。
  sslVerify: true,
  // 跨域请求时是否携带凭证（cookies）（Boolean）。
  withCredentials: false,
  // DNS 解析时优先使用 ipv4（Boolean）。
  firstIpv4: false,
  // 定义对于给定的 HTTP 状态码返回拦截状态（Function）。如果 validateStatus 返回 true（或者设置为 null），响应数据会进到响应拦截器的 onFulfilled ，否则进到 onRejected。
  validateStatus: statusCode => statusCode >= 200 && statusCode < 300,
  // 获取每次请求的 RequestTask 对象（Function）。
  xhr: undefined,
  // 定义处理请求（Function）。通过该属性可自定义请求方法，有着较强的可扩展性，一旦修改则替换默认的请求方法。
  // 该属性类型为函数类型，需返回一个 Promise（参见源码 /lib/adapters/http.js ）。
  // 且该函数有两个参数 config 和 Request，config 为每次请求的请求配置，Request 为请求方法的构造函数。
  adapter: (config, Request) => new Promise( /*...*/ ),
  // 收到开发者服务器成功返回的回调函数（Function）。该属性无法在实例配置上定义，只能在请求方法上。
  success: undefined,
  // 接口调用失败的回调函数（Function）。该属性无法在实例配置上定义，只能在请求方法上。
  fail: undefined,
  // 接口调用结束的回调函数（调用成功、失败都会执行）（Function）。该属性无法在实例配置上定义，只能在请求方法上。
  complete: undefined,
};

/** Ajax配置选项 */
const ajaxOptions = {
  /** 身份验证方案
   *  ，See https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication#authentication_schemes
   *  ，authentication schemes，e.g: Bearer
   */
  authenticationScheme: 'Bearer',
  // // 请求根地址（String）。自动加在 url 前面，除非 url 是一个绝对地址 (http 或 https 开头)。
  // baseURL: '',
  // // 开发者服务器接口地址（String）。
  // url: '',
  // 请求的参数（Object）。如果在创建实例时设定该属性，后面的实例请求方法会合并 data。
  // data: null,
  // 请求头（Object）。header 中不能设置 Referer。这里的 header 也可以为不同请求方式添加对应的请求头（注意这里的请求方式属性要小写），以及 common 公共请求头属性。
  // header 不仅可以在创建实例配置中，也可以在请求拦截器中修改配置。
  // 如果是json格式 header: { 'Content-Type': 'application/json;charset=UTF-8' },
  // 如果是form-data qs格式 header: { 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8' },
  // 如果是form-data  upload格式 header: { 'Content-Type': 'multipart/form-data;charset=UTF-8' },
  header: {
    'Content-Type': contentTypeEnum.JSON
  },
  // // 请求方式（String）。在实例中配置可定义 ajax() 方法在没有传入指定的 method 的情况下的请求方式。
  // method: 'GET',
  // // URL 的 query 参数（Object）。会将数据转换为 query string 拼接在 URL 上。
  // query: null,
  // // URL 的 params 参数（Object）。会替换掉 URL 上的 params 字段。
  // params: null,
  // 超时时间（Number）。单位 ms。
  timeout: 21600 * 1000,
  // // 返回数据类型（String）。如果设为 json，会尝试对返回的数据做一次 JSON.parse。
  // dataType: 'json',
  // // 响应的数据类型（'text' ｜ 'arraybuffer'）。
  // responseType: 'text',
  // // 是否验证 ssl 证书（Boolean）。
  // sslVerify: true,
  // // 跨域请求时是否携带凭证（cookies）（Boolean）。
  // withCredentials: false,
  // // DNS 解析时优先使用 ipv4（Boolean）。
  // firstIpv4: false,
  // // 定义对于给定的 HTTP 状态码返回拦截状态（Function）。如果 validateStatus 返回 true（或者设置为 null），响应数据会进到响应拦截器的 onFulfilled ，否则进到 onRejected。
  // validateStatus: statusCode => statusCode >= 200 && statusCode < 300,
  // // 获取每次请求的 RequestTask 对象（Function）。
  // xhr: undefined,
  // // 定义处理请求（Function）。通过该属性可自定义请求方法，有着较强的可扩展性，一旦修改则替换默认的请求方法。
  // // 该属性类型为函数类型，需返回一个 Promise（参见源码 /lib/adapters/http.js ）。
  // // 且该函数有两个参数 config 和 Request，config 为每次请求的请求配置，Request 为请求方法的构造函数。
  // adapter: (config, Request) => new Promise( /*...*/ ),
  // // 收到开发者服务器成功返回的回调函数（Function）。该属性无法在实例配置上定义，只能在请求方法上。
  // success: undefined,
  // // 接口调用失败的回调函数（Function）。该属性无法在实例配置上定义，只能在请求方法上。
  // fail: undefined,
  // // 接口调用结束的回调函数（调用成功、失败都会执行）（Function）。该属性无法在实例配置上定义，只能在请求方法上。
  // complete: undefined,
  /** 配置项，下面的选项都可以在独立的接口请求中覆盖 */
  requestOptions: {
    /** 默认将prefix 添加到url */
    joinPrefix: true,
    /** 接口拼接地址前缀 */
    urlPrefix: config.urlPrefix,
    /** 格式化提交参数时间 */
    formatDate: true,
    /** 是否加入时间戳 */
    joinTime: true,
    /** 忽略重复请求 */
    ignoreCancelToken: true,
    /** 是否携带token */
    withToken: true,
    /** 是否返回原生响应头 比如：需要获取响应头时使用该属性 */
    isReturnNativeResponse: false,
    /** 需要对返回数据进行处理 */
    isTransformResponse: true,
    /** 消息提示类型 */
    errorMessageMode: 'message',
  },
};

/** 上传文件配置选项 */
const uploadConfig = {
  /** 身份验证方案
   *  ，See https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication#authentication_schemes
   *  ，authentication schemes，e.g: Bearer
   */
  authenticationScheme: 'Bearer',
  // String	是	开发者服务器 url
  url: '',
  // Array	是（files和filePath选其一）	需要上传的文件列表。使用 files 时，filePath 和 name 不生效。	App、H5（ 2.6.15+）
  // {name:'String multipart 提交时，表单的项目名，默认为 file', file: File 要上传的文件对象，仅H5（2.6.15+）支持, uri: 'String 文件的本地地址' }
  files: [],
  // String	见平台差异说明	文件类型，image/video/audio	仅支付宝小程序，且必填。
  fileType: '',
  // File	否	要上传的文件对象。	仅H5（2.6.15+）支持
  file: null,
  // String	是（files和filePath选其一）	要上传文件资源的路径。
  filePath: '',
  // String	是	文件对应的 key , 开发者在服务器端通过这个 key 可以获取到文件二进制内容
  name: 'file',
  // Object	否	HTTP 请求 Header, header 中不能设置 Referer。
  header: {},
  // Number	否	超时时间，单位 ms	H5(HBuilderX 2.9.9+)、APP(HBuilderX 2.9.9+)
  timeout: 120 * 1000,
  // Object	否	HTTP 请求中其他额外的 form data
  formData: {},
  // Function	否	接口调用成功的回调函数
  success: undefined,
  // Function	否	接口调用失败的回调函数
  fail: undefined,
  // Function	否	接口调用结束的回调函数（调用成功、失败都会执行）
  complete: undefined,
  /** 配置项，下面的选项都可以在独立的接口请求中覆盖 */
  requestOptions: {
    /** 默认将prefix 添加到url */
    joinPrefix: true,
    /** 接口拼接地址前缀 */
    urlPrefix: config.urlPrefix,
    /** 忽略重复请求 */
    ignoreCancelToken: true,
    /** 是否携带token */
    withToken: true,
    /** 是否返回原生响应头 比如：需要获取响应头时使用该属性 */
    isReturnNativeResponse: false,
    /** 需要对返回数据进行处理 */
    isTransformResponse: true,
    /** 消息提示类型 */
    errorMessageMode: 'message',
  },
};

/** 下载文件配置选项 */
const downloadConfig = {
  /** 身份验证方案
   *  ，See https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication#authentication_schemes
   *  ，authentication schemes，e.g: Bearer
   */
  authenticationScheme: 'Bearer',
  // String	是	开发者服务器 url
  url: '',
  // Object	否	HTTP 请求 Header, header 中不能设置 Referer。
  header: {},
  // Number	否	超时时间，单位 ms	H5(HBuilderX 2.9.9+)、APP(HBuilderX 2.9.9+)
  timeout: 120 * 1000,
  // Function	否	下载成功后以 tempFilePath 的形式传给页面，res = {statusCode: 'HTTP 状态码', tempFilePath: '文件的临时路径'}
  // 文件的临时路径，在应用本次启动期间可以正常使用，如需持久保存，需在主动调用 uni.saveFile，才能在应用下次启动时访问得到。
  success: undefined,
  // Function	否	接口调用失败的回调函数
  fail: undefined,
  // Function	否	接口调用结束的回调函数（调用成功、失败都会执行）
  complete: undefined,
  // String	否	指定文件下载后存储的路径 (本地路径)
  filePath: '',
  /** 配置项，下面的选项都可以在独立的接口请求中覆盖 */
  requestOptions: {
    /** 默认将prefix 添加到url */
    joinPrefix: true,
    /** 接口拼接地址前缀 */
    urlPrefix: config.urlPrefix,
    /** 忽略重复请求 */
    ignoreCancelToken: true,
    /** 是否携带token */
    withToken: true,
    /** 消息提示类型 */
    errorMessageMode: 'message',
  },
};

/** 创建Http请求客户端 */
export function createAjax(defaultConfig) {
  // 挂载当前实例配置
  const config = typeof defaultConfig === 'object' ? merge(ajaxOptions, defaultConfig || {}) : ajaxOptions;

  // 创建请求实例
  const instance = ajax.create(config);

  // 在 Ajax 实例上挂载 upload 方法
  instance.upload = function(uploadInOptions, callback) {
    // 挂载配置
    let uploadOptions = typeof uploadInOptions === 'object' ? merge(uploadConfig, uploadInOptions || {}) :
      uploadConfig;
    // console.log('upload', {uploadConfig,uploadInOptions,uploadOptions});

    const {
      joinPrefix,
      urlPrefix,
      formatDate,
      joinTime,
      withToken
    } = uploadOptions.requestOptions;
    // const requestOptions = uploadOptions.requestOptions;

    if (joinPrefix) {
      if (
        urlPrefix !== undefined &&
        urlPrefix !== null &&
        urlPrefix !== '' &&
        isString(urlPrefix)
      ) {
        uploadOptions.url = `${urlPrefix}${uploadOptions.url}`;
      }
    }
    // 设置基础地址（根据地址前缀）
    const apiUrl = getApiUrl();
    if (uploadOptions.url.startsWith('/api')) {
      uploadOptions.url = `${apiUrl}${uploadOptions.url}`;
    } else if (uploadOptions.url.startsWith('/file')) {
      const fileUrl = getFileUrl();
      uploadOptions.url = `${fileUrl}${uploadOptions.url}`;
    } else if (uploadOptions.url.startsWith('/upload')) {
      const uploadUrl = getUploadUrl();
      uploadOptions.url = `${uploadUrl}${uploadOptions.url}`;
    } else {
      uploadOptions.url = `${apiUrl}${uploadOptions.url}`;
    }

    // jwt token
    const accessToken = store.getters.getAccessToken;
    if (accessToken && withToken === true) {
      uploadOptions.header.Authorization = uploadOptions.authenticationScheme ?
        `${uploadOptions.authenticationScheme} ${accessToken}` :
        accessToken;
      // uploadOptions.header = {
      // 	...uploadOptions.header,
      // 	'Authorization': uploadOptions.authenticationScheme ?
      // 		`${uploadOptions.authenticationScheme} ${accessToken}` : accessToken
      // };
    }
    // 请求语言
    const currentRequestlang = getCurrentRequestlang();
    if (currentRequestlang !== undefined && currentRequestlang !== null && currentRequestlang !== '') {
      // console.log('请求语言', currentRequestlang);
      uploadOptions.header = {
        ...uploadOptions.header,
        'Accept-Language': currentRequestlang
      };
    }

    // 如果希望返回一个 uploadTask 对象，需要至少传入 success / fail / complete 参数中的一个。通过 uploadTask，可监听上传进度变化事件，以及取消上传任务。
    // 如果没有传入 success / fail / complete 参数，则会返回封装后的 Promise 对象。
    let uploadTask;
    // uploadTask = uni.uploadFile(uploadOptions);
    // if (typeof callback === 'function') {
    // 	callback(uploadTask)
    // }
    // return uploadTask;
    return new Promise(async (resolve, reject) => {
      uploadOptions.complete = undefined;
      uploadTask = uni.uploadFile({
        ...uploadOptions,
        complete: (res) => {
          // console.log('upload_complete', res);
          const {
            t
          } = useI18n();

          const {
            isTransformResponse,
            isReturnNativeResponse,
            errorMessageMode
          } = uploadOptions.requestOptions;
          // const requestOptions = uploadOptions.requestOptions;

          // 是否返回原生响应头 比如：需要获取响应头时使用该属性
          if (isReturnNativeResponse === true) {
            resolve(res);
            return;
            // return res;
          }
          if (res.statusCode === 200) {
            // 不进行任何处理，直接返回
            // 用于页面代码可能需要直接获取code，data，message这些信息时开启
            if (isTransformResponse === false) {
              resolve(res.data);
              return;
              // return res.data;
            }

            const {
              data: result
            } = res;
            if (result === undefined) {
              // return '[HTTP] Request has no return value';
              reject(t('api.requestHasNoReturnValue'));
              return;
            }
            // 返回值为null，直接返回。
            if (result === null) {
              resolve(result);
              return;
            }

            // 这里 code，result，message为 后台统一的字段，需要在 types.ts内修改为项目自己的接口返回格式
            const {
              Type,
              Content,
              Data,
              Succeeded,
              Failed
            } = result;
            //非AjaxResult类型，直接返回。
            if (
              !(
                Content !== undefined &&
                Data !== undefined &&
                Type !== undefined &&
                Type !== null &&
                Succeeded !== undefined &&
                Succeeded !== null &&
                Failed !== undefined &&
                Failed !== null &&
                isNumber(Type) &&
                isBoolean(Succeeded) &&
                isBoolean(Failed)
              )
            ) {
              resolve(result);
              return;
              // return result;
            }

            // 接口请求成功，直接返回结果
            // 这里逻辑可以根据项目进行修改
            const hasSuccess = result && Reflect.has(result, 'Type') &&
              Type === 200;
            if (hasSuccess) {
              resolve(result);
              return;
              // return result;
            }

            checkStatus(Type, Content, errorMessageMode);

            reject({
              Type: 500,
              Content: t('api.requestError'),
              Data: null
            });
            return;
          } else {
            if (res.statusCode !== undefined && res.statusCode !== null &&
              res.statusCode !== 'undefined') {
              checkStatus(res.statusCode, res.errMsg, errorMessageMode);
            }
            reject(res);
          }
        }
      });
      if (typeof callback === 'function') {
        callback(uploadTask)
      }
    });

    // uploadTask使用示例
    // uploadTask.onProgressUpdate((res) => {
    // 	console.log('上传进度' + res.progress);
    // 	console.log('已经上传的数据长度' + res.totalBytesSent);
    // 	console.log('预期需要上传的数据总长度' + res.totalBytesExpectedToSend);

    // 	// 测试条件，取消上传任务。
    // 	if (res.progress > 50) {
    // 	    uploadTask.abort();
    // 	}
    // });
  };

  // 在 Ajax 实例上挂载 download 方法
  instance.download = function(downloadInOptions, callback) {
    // 挂载配置
    let downloadOptions = typeof downloadInOptions === 'object' ? merge(downloadConfig, downloadInOptions || {}) :
      downloadConfig;
    // console.log('download', {downloadConfig,downloadInOptions,downloadOptions});

    const {
      joinPrefix,
      urlPrefix,
      formatDate,
      joinTime,
      withToken
    } = downloadOptions.requestOptions;
    // const requestOptions = downloadOptions.requestOptions;

    if (joinPrefix) {
      if (
        urlPrefix !== undefined &&
        urlPrefix !== null &&
        urlPrefix !== '' &&
        isString(urlPrefix)
      ) {
        downloadOptions.url = `${urlPrefix}${downloadOptions.url}`;
      }
    }
    // 设置基础地址（根据地址前缀）
    const apiUrl = getApiUrl();
    if (downloadOptions.url.startsWith('/api')) {
      downloadOptions.url = `${apiUrl}${downloadOptions.url}`;
    } else if (downloadOptions.url.startsWith('/file')) {
      const fileUrl = getFileUrl();
      downloadOptions.url = `${fileUrl}${downloadOptions.url}`;
    } else if (downloadOptions.url.startsWith('/upload')) {
      const downloadUrl = getUploadUrl();
      downloadOptions.url = `${downloadUrl}${downloadOptions.url}`;
    } else {
      downloadOptions.url = `${apiUrl}${downloadOptions.url}`;
    }

    // jwt token
    const accessToken = store.getters.getAccessToken;
    if (accessToken && withToken === true) {
      downloadOptions.header.Authorization = downloadOptions.authenticationScheme ?
        `${downloadOptions.authenticationScheme} ${accessToken}` :
        accessToken;
      // downloadOptions.header = {
      // 	...downloadOptions.header,
      // 	'Authorization': downloadOptions.authenticationScheme ?
      // 		`${downloadOptions.authenticationScheme} ${accessToken}` : accessToken
      // };
    }
    // 请求语言
    const currentRequestlang = getCurrentRequestlang();
    if (currentRequestlang !== undefined && currentRequestlang !== null && currentRequestlang !== '') {
      // console.log('请求语言', currentRequestlang);
      downloadOptions.header = {
        ...downloadOptions.header,
        'Accept-Language': currentRequestlang
      };
    }

    // // 用于解决 Refused to get unsafe header "content-disposition"
    // downloadOptions.header = {
    // 	...downloadOptions.header,
    // 	'Access-Control-Expose-Headers': 'Content-Disposition'
    // };

    // 如果希望返回一个 downloadTask 对象，需要至少传入 success / fail / complete 参数中的一个。通过 downloadTask，可监听上传进度变化事件，以及取消上传任务。
    // 如果没有传入 success / fail / complete 参数，则会返回封装后的 Promise 对象。
    let downloadTask;
    // downloadTask = uni.downloadFile(downloadOptions);
    // if (typeof callback === 'function') {
    // 	callback(downloadTask)
    // }
    // return downloadTask;
    return new Promise(async (resolve, reject) => {
      downloadOptions.complete = undefined;
      downloadTask = uni.downloadFile({
        ...downloadOptions,
        complete: (res) => {
          // console.log('download_complete', res);
          const {
            t
          } = useI18n();

          const {
            errorMessageMode
          } = downloadOptions.requestOptions;
          // const requestOptions = downloadOptions.requestOptions;

          if (res.statusCode === 200) {
            // console.log('下载成功', res);
            resolve(res.tempFilePath);
            return;
          } else {
            // console.log('下载失败', JSON.stringify(res));
            if (res.statusCode !== undefined && res.statusCode !== null &&
              res.statusCode !== 'undefined') {
              checkStatus(res.statusCode, JSON.stringify(res),
                errorMessageMode);
            }
            reject(res);
          }
        }
      });
      if (typeof callback === 'function') {
        callback(downloadTask)
      }
    });

    // downloadTask使用示例
    // downloadTask.onProgressUpdate((res) => {
    //     console.log('下载进度' + res.progress);
    //     console.log('已经下载的数据长度' + res.totalBytesWritten);
    //     console.log('预期需要下载的数据总长度' + res.totalBytesExpectedToWrite);

    //     // 满足测试条件，取消下载任务。
    //     if (res.progress > 50) {
    //         downloadTask.abort();
    //     }
    // });
  };

  // 添加请求拦截器
  instance.interceptors.request.use(
    config => {
      // 在发送请求前做些什么
      // console.log('请求拦截处理前', config);

      const {
        joinPrefix,
        urlPrefix,
        formatDate,
        joinTime,
        withToken
      } = config.requestOptions;
      // const requestOptions = config.requestOptions;

      if (joinPrefix) {
        if (
          urlPrefix !== undefined &&
          urlPrefix !== null &&
          urlPrefix !== '' &&
          isString(urlPrefix)
        ) {
          config.url = `${urlPrefix}${config.url}`;
        }
      }
      // 设置基础地址（根据地址前缀）
      if (config.url.startsWith('/api')) {
        const apiUrl = getApiUrl();
        config.url = `${apiUrl}${config.url}`;
      } else if (config.url.startsWith('/file')) {
        const fileUrl = getFileUrl();
        config.url = `${fileUrl}${config.url}`;
      } else if (config.url.startsWith('/upload')) {
        const uploadUrl = getUploadUrl();
        config.url = `${uploadUrl}${config.url}`;
      } else {
        const apiUrl = getApiUrl();
        config.url = `${apiUrl}${config.url}`;
      }

      // 给 get 请求加上时间戳参数，避免从缓存中拿数据。
      const params = config.query || {};
      if (config.method?.toUpperCase() === requestMethodEnum.GET) {
        // 兼容restful风格
        config.url = `${config.url}${joinTimestamp(joinTime, true)}`;
      }

      // 格式化请求参数的日期属性值
      const data = config.data || false;
      formatDate && data && !isString(data) && formatRequestDate(data);

      // jwt token
      const accessToken = store.getters.getAccessToken;
      if (accessToken && withToken === true) {
        config.header.Authorization = config.authenticationScheme ?
          `${config.authenticationScheme} ${accessToken}` :
          accessToken;
        // config.header = {
        // 	...config.header,
        // 	'Authorization': config.authenticationScheme ?
        // 		`${config.authenticationScheme} ${accessToken}` : accessToken
        // };
      }
      // 请求语言
      const currentRequestlang = getCurrentRequestlang();
      if (currentRequestlang !== undefined && currentRequestlang !== null && currentRequestlang !== '') {
        // console.log('请求语言', currentRequestlang);
        config.header = {
          ...config.header,
          'Accept-Language': currentRequestlang
        };
      }

      // console.log('请求拦截处理后', config);
      return config;
    },
    error => {
      // 对请求错误做些什么
      console.log('发请求错误', error);

      const errorMessageMode = error.config.requestOptions.errorMessageMode;
      if (errorMessageMode === 'modal') {
        uni.showModal({
          title: 'error',
          content: error.errMsg,
          showCancel: false
        });
      } else if (errorMessageMode === 'message') {
        uni.showToast({
          title: error.errMsg,
          // duration: 2000,
          icon: 'none'
        });
      }

      return Promise.reject(error);
    }
  );

  // 添加响应拦截器
  instance.interceptors.response.use(
    response => {
      // 对响应数据做些什么
      // console.log('响应成功后', response);
      const {
        t
      } = useI18n();

      const res = response;
      const {
        isTransformResponse,
        isReturnNativeResponse,
        errorMessageMode
      } = response.config.requestOptions;
      // const requestOptions = response.config.requestOptions;

      // 是否返回原生响应头 比如：需要获取响应头时使用该属性
      if (isReturnNativeResponse === true) {
        return res;
      }
      // 不进行任何处理，直接返回
      // 用于页面代码可能需要直接获取code，data，message这些信息时开启
      if (isTransformResponse === false) {
        return res.data;
      }

      const {
        data: result
      } = res;
      if (result === undefined) {
        // return '[HTTP] Request has no return value';
        throw new Error(t('api.requestHasNoReturnValue'));
      }
      // 返回值为null，直接返回。
      if (result === null) {
        return result;
      }

      // 这里 code，result，message为 后台统一的字段，需要在 types.ts内修改为项目自己的接口返回格式
      const {
        Type,
        Content,
        Data,
        Succeeded,
        Failed
      } = result;
      //非AjaxResult类型，直接返回。
      if (
        !(
          Content !== undefined &&
          Data !== undefined &&
          Type !== undefined &&
          Type !== null &&
          Succeeded !== undefined &&
          Succeeded !== null &&
          Failed !== undefined &&
          Failed !== null &&
          isNumber(Type) &&
          isBoolean(Succeeded) &&
          isBoolean(Failed)
        )
      ) {
        return result;
      }

      // 这里逻辑可以根据项目进行修改
      const hasSuccess = result && Reflect.has(result, 'Type') && Type === 200;
      // 接口请求成功，直接返回结果
      if (hasSuccess) {
        return result;
      }

      checkStatus(Type, Content, errorMessageMode);

      return result;
      // return {
      // 	Type: 500,
      // 	Content: t('api.requestError'),
      // 	Data: null
      // };
      //return Promise.reject(t('api.requestError'));

      // 接口请求失败，处理失败逻辑
      // 在此处根据自己项目的实际情况对不同的code执行不同的操作
      // 如果不希望中断当前请求，请return数据，否则直接抛出异常即可
      // let timeoutMsg = '';
      // switch (Type) {
      // 	case 401:
      // 		timeoutMsg = t('sys.api.timeoutMessage');
      // 		store.dispatch("logout", false);
      // 		uni.navigateTo({
      // 			url: '/pages/sys/login/login',
      // 			passedParams: {
      // 				info: '未登陆',
      // 			},
      // 		});
      // 		break;
      // 	default:
      // 		if (Content) {
      // 			timeoutMsg = Content;
      // 		}
      // }

      // // errorMessageMode=‘modal’的时候会显示modal错误弹窗，而不是消息提示，用于一些比较重要的错误
      // // errorMessageMode='none' 一般是调用时明确表示不希望自动弹出错误提示
      // if (options.errorMessageMode === 'modal') {
      // 	uni.showModal({
      // 		title: t('sys.api.errorTip'),
      // 		content: timeoutMsg,
      // 		showCancel: false
      // 	});
      // } else if (options.errorMessageMode === 'message') {
      // 	uni.showToast({
      // 		title: timeoutMsg,
      // 		// duration: 2000,
      //		icon: 'none'
      // 	});
      // }

      // throw new Error(timeoutMsg || t('sys.api.requestError'));
    },
    error => {
      // 对响应错误做些什么
      console.log('响应错误后', error);

      let status = error.statusCode;
      let errorMsg = error.errMsg;
      if (error && error.data && error.data.status) {
        status = error.data.status;
        if (error.data.title) {
          errorMsg = error.data.title;
        }
        // console.log('响应错误后', error.data.errors);
        if (error.data.errors) {
          errorMsg = JSON.stringify(error.data.errors);
        }
      }

      checkStatus(status, errorMsg, error.config.requestOptions.errorMessageMode);

      // const errorMessageMode = error.config.requestOptions.errorMessageMode;
      // if (errorMessageMode === 'modal') {
      // 	uni.showModal({
      // 		title: 'error',
      // 		content: errorMsg,
      // 		showCancel: false
      // 	});
      // } else if (errorMessageMode === 'message') {
      // 	uni.showToast({
      // 		title: errorMsg,
      // 		// duration: 2000,
      //		icon: 'none'
      // 	});
      // }

      return Promise.reject(error);
    }
  );

  return instance;
}

/** Http请求客户端 */
const request = createAjax();

// other api url
// export const otherRequest = createAjax({
//   requestOptions: {
//     urlPrefix: 'xxx',
//   },
// });

export default request;
